home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / hplip / sendfax < prev    next >
Encoding:
Text File  |  2007-04-04  |  24.1 KB  |  746 lines

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # (c) Copyright 2003-2007 Hewlett-Packard Development Company, L.P.
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program; if not, write to the Free Software
  18. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  19. #
  20. # Author: Don Welch
  21. #
  22. # Thanks to Henrique M. Holschuh <hmh@debian.org> for various security patches
  23. #
  24.  
  25. __version__ = '5.1'
  26. __title__ = 'PC Sendfax Utility'
  27. __doc__ = "Allows for sending faxes from the PC using HPLIP supported multifunction printers." 
  28.  
  29. # Std Lib
  30. import sys, socket, os, os.path, getopt, signal, atexit
  31. import ConfigParser, pwd, socket, time
  32.  
  33. # Local
  34. from base.g import *
  35. from base.msg import *
  36. import base.utils as utils
  37. from base import device, service
  38.  
  39. log.set_module('hp-sendfax')
  40.  
  41. USAGE = [(__doc__, "", "name", True),
  42.          ("Usage: hp-sendfax [PRINTER|DEVICE-URI] [OPTIONS] [MODE] [FILES]", "", "summary", True),
  43.          utils.USAGE_ARGS,
  44.          utils.USAGE_DEVICE,
  45.          utils.USAGE_PRINTER,
  46.          utils.USAGE_SPACE,
  47.          ("[MODE]", "", "header", False),
  48.          ("Enter graphical UI mode:", "-u or --gui (Default)", "option", False),
  49.          ("Run in non-interactive mode (batch mode):", "-n or --non-interactive", "option", False),
  50.          utils.USAGE_SPACE,
  51.          utils.USAGE_OPTIONS,
  52.          ("Specify the fax number(s):", "-f<number(s)> or --faxnum=<number(s)> (-n only)", "option", False),
  53.          ("Specify the recipient(s):", "-r<recipient(s)> or --recipient=<recipient(s)> (-n only)", "option", False), 
  54.          ("Specify the groups(s):", "-g<group(s)> or --group=<group(s)> (-n only)", "option", False), 
  55.          ("Use pretty printing for text files:", "-t or --prettyprint (-n only)", "option", False),
  56.          utils.USAGE_BUS1, utils.USAGE_BUS2,         
  57.          utils.USAGE_LOGGING1, utils.USAGE_LOGGING2,# utils.USAGE_LOGGING3,
  58.          ("Run in debug mode:", "--gg (same as option: -ldebug)", "option", False),
  59.          utils.USAGE_HELP,
  60.          ("[FILES]", "", "header", False),
  61.          ("A list of files to add to the fax job.", "(Required for -n, optional for -u)", "option", True),
  62.          utils.USAGE_NOTES,
  63.          utils.USAGE_STD_NOTES1,
  64.          utils.USAGE_STD_NOTES2,
  65.          ("3. Coversheets are not supported in non-interactive mode (-n)", "", "note", False),
  66.          ("4. Fax numbers and/or recipients should be listed in comma separated lists (-n only).", "", "note", False),
  67.          utils.USAGE_SPACE,
  68.          utils.USAGE_SEEALSO,
  69.          ("hp-fab", "", "seealso", False),
  70.         ]
  71.  
  72. def usage(typ='text'):
  73.     if typ == 'text':
  74.         utils.log_title(__title__, __version__)
  75.  
  76.     utils.format_text(USAGE, typ, __title__, 'hp-sendfax', __version__)
  77.     sys.exit(0)
  78.  
  79.  
  80.  
  81. prop.prog = sys.argv[0]
  82.  
  83. device_uri = None
  84. printer_name = None
  85. username = prop.username
  86. mode = GUI_MODE
  87. mode_specified = False
  88. faxnum_list = []
  89. recipient_list = []
  90. group_list = []
  91. bus = device.DEFAULT_PROBE_BUS
  92. prettyprint = False
  93.  
  94. try:
  95.     opts, args = getopt.getopt(sys.argv[1:],'l:hz:d:p:b:g:unf:r:t', 
  96.         ['device=', 'printer=', 'level=', 
  97.          'help', 'help-rest', 
  98.          'help-man', 'logfile=', 'bus=',
  99.          'gui', 'non-interactive',
  100.          'faxnum=', 'recipients=',
  101.          'gg', 'groups', 'help-desc', 'prettyprint'])
  102.  
  103. except getopt.GetoptError, e:
  104.     log.error(e)
  105.     sys.exit(1)
  106.  
  107.  
  108. if os.getenv("HPLIP_DEBUG"):
  109.     log.set_level('debug')
  110.  
  111. for o, a in opts:
  112.     if o in ('-l', '--logging'):
  113.         log_level = a.lower().strip()
  114.         if not log.set_level(log_level):
  115.             usage()
  116.  
  117.     elif o == '--gg':
  118.         log.set_level('debug')
  119.  
  120.     elif o in ('-z', '--logfile'):
  121.         log.set_logfile(a)
  122.         log.set_where(log.LOG_TO_CONSOLE_AND_FILE)
  123.  
  124.     elif o in ('-h', '--help'):
  125.         usage()
  126.  
  127.     elif o == '--help-rest':
  128.         usage('rest')
  129.  
  130.     elif o == '--help-man':
  131.         usage('man')
  132.  
  133.     elif o == '--help-desc':
  134.         print __doc__,
  135.         sys.exit(0)
  136.  
  137.     elif o in ('-d', '--device'):
  138.         device_uri = a
  139.  
  140.     elif o in ('-p', '--printer'):
  141.         printer_name = a
  142.  
  143.     elif o in ('-b', '--bus'):
  144.         bus = a.lower().strip()
  145.         if not device.validateBusList(bus):
  146.             usage()
  147.  
  148.     elif o in ('-n', '--non-interactive'):
  149.         if mode_specified:
  150.             log.error("You may only specify a single mode as a parameter (-n or -u).")
  151.             sys.exit(1)
  152.  
  153.         mode = NON_INTERACTIVE_MODE
  154.         mode_specified = True
  155.  
  156.     elif o in ('-u', '--gui'):
  157.         if mode_specified:
  158.             log.error("You may only specify a single mode as a parameter (-n or -u).")
  159.             sys.exit(1)
  160.  
  161.         mode = GUI_MODE
  162.         mode_specified = True
  163.  
  164.     elif o in ('-f', '--faxnum'):
  165.         faxnum_list.extend(a.split(','))
  166.  
  167.     elif o in ('-r', '--recipient'):
  168.         recipient_list.extend(a.split(','))
  169.  
  170.     elif o in ('-g', '--group'):
  171.         group_list.extend(a.split(','))
  172.  
  173.     elif o in ('-t', '--prettyprint'):
  174.         prettyprint = True
  175.  
  176.  
  177. utils.log_title(__title__, __version__)
  178.  
  179. # Security: Do *not* create files that other users can muck around with
  180. os.umask (0077)
  181.  
  182. if mode == GUI_MODE:
  183.     if not os.getenv('DISPLAY'):
  184.         mode = NON_INTERACTIVE_MODE
  185.  
  186.     elif not utils.checkPyQtImport():
  187.         mode = NON_INTERACTIVE_MODE
  188.  
  189. if mode == GUI_MODE:
  190.     app = None
  191.     sendfax = None
  192.  
  193.     from qt import *
  194.  
  195.     # UI Forms
  196.     from ui.faxsendjobform import FaxSendJobForm
  197.  
  198.     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  199.     try:
  200.         sock.connect((prop.hpssd_host, prop.hpssd_port))
  201.     except socket.error:
  202.         log.error("Unable to connect to HPLIP I/O (hpssd).")
  203.         sys.exit(1)
  204.  
  205.     # create the main application object
  206.     app = QApplication(sys.argv)
  207.  
  208.     sendfax = FaxSendJobForm(sock,
  209.                              device_uri,  
  210.                              printer_name, 
  211.                              args) 
  212.  
  213.     app.setMainWidget(sendfax)
  214.  
  215.     pid = os.getpid()
  216.     log.debug('pid=%d' % pid)
  217.  
  218.     sendfax.show()
  219.  
  220.     signal.signal(signal.SIGPIPE, signal.SIG_IGN)
  221.  
  222.     user_config = os.path.expanduser('~/.hplip.conf')
  223.     loc = utils.loadTranslators(app, user_config)
  224.  
  225.     try:
  226.         log.debug("Starting GUI loop...")
  227.         app.exec_loop()
  228.     except KeyboardInterrupt:
  229.         pass
  230.     except:
  231.         log.exception()
  232.  
  233. else: # NON_INTERACTIVE_MODE
  234.     import struct, Queue
  235.  
  236.     from prnt import cups
  237.     from base import magic, msg
  238.  
  239.     try:
  240.         from fax import fax
  241.     except ImportError:
  242.         # This can fail on Python < 2.3 due to the datetime module
  243.         log.error("Fax address book disabled - Python 2.3+ required.")
  244.         sys.exit(1)    
  245.  
  246.     db =  fax.FaxAddressBook() # kirbybase instance
  247.  
  248.     phone_num_list = []
  249.  
  250.     log.debug("Faxnum list = %s" % faxnum_list)
  251.     faxnum_list = utils.uniqueList(faxnum_list)
  252.     log.debug("Unique list=%s" % faxnum_list)
  253.  
  254.     for f in faxnum_list:
  255.         for c in f:
  256.             if c not in '0123456789-(+) *#':
  257.                 log.error("Invalid character in fax number '%s'. Only the characters '0123456789-(+) *#' are valid." % f)
  258.                 sys.exit(1)
  259.  
  260.     log.debug("Group list = %s" % group_list)
  261.     group_list = utils.uniqueList(group_list)
  262.     log.debug("Unique list=%s" % group_list)
  263.  
  264.     for g in group_list:
  265.         entries = db.GroupEntries(g)
  266.         for e in entries:
  267.             recipient_list.append(e)
  268.  
  269.     log.debug("Recipient list = %s" % recipient_list)
  270.     recipient_list = utils.uniqueList(recipient_list)
  271.     log.debug("Unique list=%s" % recipient_list)
  272.  
  273.     for r in recipient_list:
  274.         if not db.select(['name'], [r]):
  275.             log.error("Unknown fax recipient '%s' in the recipient list." % r)
  276.             all_entries = db.AllRecordEntries()
  277.             log.info(utils.bold("\nKnown recipients (entries):"))
  278.  
  279.             for a in all_entries:
  280.                 log.info(a.name)
  281.  
  282.             print
  283.             sys.exit(1)
  284.  
  285.     for p in recipient_list:
  286.         a = fax.AddressBookEntry(db.select(['name'], [p])[0])
  287.         phone_num_list.append(a)
  288.         log.debug("Name=%s Number=%s" % (a.name, a.fax))
  289.  
  290.     for p in faxnum_list:
  291.         a = fax.AddressBookEntry((-1, "Unknown", "Unknown", "Unknown", "Unknown", p, "", ""))
  292.         phone_num_list.append(a)
  293.         log.debug("Name=%s Number=%s" % (a.name, a.fax))
  294.  
  295.     log.debug("Phone num list = %s" % phone_num_list)
  296.  
  297.     if not phone_num_list:
  298.         log.error("No recipients specified. Please use -f, -r, and/or -g to specify recipients.")
  299.         usage()
  300.  
  301.     allowable_mime_types = cups.getAllowableMIMETypes()
  302.     allowable_mime_types.append("application/hplip-fax")
  303.     allowable_mime_types.append("application/x-python")
  304.  
  305.     for f in args:
  306.         path = os.path.realpath(f)
  307.         log.debug(path)
  308.  
  309.         if os.path.exists(path):
  310.             mime_type = magic.mime_type(path)
  311.             log.debug(mime_type)
  312.         else:
  313.             log.error("File '%s' does not exist." % path)
  314.             sys.exit(1)
  315.  
  316.         if mime_type not in allowable_mime_types:
  317.             log.error("File '%s' has a non-allowed mime-type of '%s'" % (path, mime_type))
  318.             sys.exit(1)
  319.  
  320.     if printer_name:
  321.         printer_list = cups.getPrinters()
  322.         found = False
  323.         for p in printer_list:
  324.             if p.name == printer_name:
  325.                 device_uri = p.device_uri
  326.                 found = True
  327.                 break
  328.  
  329.         if not found:
  330.             log.error("Unknown printer name: %s" % printer_name)
  331.             sys.exit(1)
  332.  
  333.         if not p.device_uri.startswith('hpfax:/'):
  334.             log.error("You must specify a printer that has a device URI in the form 'hpfax:/'")
  335.             sys.exit(1)
  336.  
  337.     if device_uri and not printer_name:
  338.         cups_printers = cups.getPrinters()
  339.  
  340.         max_printer_size = 20
  341.         printers = []
  342.         for p in cups_printers:
  343.             try:
  344.                 back_end, is_hp, bus, model, serial, dev_file, host, port = \
  345.                     device.parseDeviceURI(p.device_uri)
  346.             except Error:
  347.                 continue
  348.  
  349.             if back_end == 'hpfax' and p.device_uri == device_uri:
  350.                 printers.append((p.name, p.device_uri))
  351.                 max_printer_size = max(len(p.name), max_printer_size)
  352.  
  353.         if not printers:
  354.             log.error("No CUPS queue found for device %s" % device_uri)
  355.             sys.exit(1)
  356.  
  357.         elif len(printers) == 1:
  358.             printer_name = printers[0][0]
  359.  
  360.         else:
  361.             log.info(utils.bold("\nChoose printer (fax queue) from installed printers in CUPS:\n"))
  362.  
  363.             formatter = utils.TextFormatter(
  364.                     (
  365.                         {'width': 4},
  366.                         {'width': max_printer_size, 'margin': 2},
  367.                     )
  368.                 )
  369.  
  370.             log.info(formatter.compose(("Num.", "CUPS Printer (queue)")))
  371.             log.info(formatter.compose(('-'*4, '-'*(max_printer_size), )))
  372.  
  373.             i = 0
  374.             for p in printers:
  375.                 log.info(formatter.compose((str(i), p[0])))
  376.                 i += 1
  377.  
  378.             while 1:
  379.                 user_input = raw_input(utils.bold("\nEnter number 0...%d for printer (q=quit) ?" % (i-1)))
  380.  
  381.                 if user_input == '':
  382.                     log.warn("Invalid input - enter a numeric value or 'q' to quit.")
  383.                     continue
  384.  
  385.                 if user_input.strip()[0] in ('q', 'Q'):
  386.                     sys.exit(1)
  387.  
  388.                 try:
  389.                     x = int(user_input)
  390.                 except ValueError:
  391.                     log.warn("Invalid input - enter a numeric value or 'q' to quit.")
  392.                     continue
  393.  
  394.                 if x < 0 or x > (i-1):
  395.                     log.warn("Invalid input - enter a value between 0 and %d or 'q' to quit." % (i-1))
  396.                     continue
  397.  
  398.                 break
  399.  
  400.             print printers[x]
  401.             printer_name = printers[x][0]
  402.  
  403.     if not device_uri and not printer_name:
  404.         cups_printers = cups.getPrinters()
  405.         log.debug(cups_printers)
  406.  
  407.         printers = []
  408.         max_deviceid_size, max_printer_size = 0, 0
  409.  
  410.         for p in cups_printers:
  411.             back_end, is_hp, bus, model, serial, dev_file, host, port = \
  412.                 device.parseDeviceURI(p.device_uri)
  413.  
  414.             if back_end == 'hpfax':
  415.                 printers.append((p.name, p.device_uri))
  416.                 max_deviceid_size = max(len(p.device_uri), max_deviceid_size)
  417.                 max_printer_size = max(len(p.name), max_printer_size)
  418.  
  419.         if not printers:
  420.             log.error("No devices found.")
  421.             sys.exit(1)
  422.  
  423.         if len(printers) == 1:
  424.             printer_name, device_uri = printers[0]
  425.  
  426.         else:
  427.             log.info(utils.bold("\nChoose printer (fax queue) from installed printers in CUPS:\n"))
  428.  
  429.             formatter = utils.TextFormatter(
  430.                     (
  431.                         {'width': 4},
  432.                         {'width': max_printer_size, 'margin': 2},
  433.                         {'width': max_deviceid_size, 'margin': 2},
  434.                     )
  435.                 )
  436.  
  437.             log.info(formatter.compose(("Num.", "CUPS Printer", "Device URI")))
  438.             log.info(formatter.compose(('-'*4, '-'*(max_printer_size), '-'*(max_deviceid_size))))
  439.  
  440.             i = 0
  441.             for p in printers:
  442.                 log.info(formatter.compose((str(i), p[0], p[1])))
  443.                 i += 1
  444.  
  445.             while 1:
  446.                 user_input = raw_input(utils.bold("\nEnter number 0...%d for printer (q=quit) ?" % (i-1)))
  447.  
  448.                 if user_input == '':
  449.                     log.warn("Invalid input - enter a numeric value or 'q' to quit.")
  450.                     continue
  451.  
  452.                 if user_input.strip()[0] in ('q', 'Q'):
  453.                     sys.exit(1)
  454.  
  455.                 try:
  456.                     x = int(user_input)
  457.                 except ValueError:
  458.                     log.warn("Invalid input - enter a numeric value or 'q' to quit.")
  459.                     continue
  460.  
  461.                 if x < 0 or x > (i-1):
  462.                     log.warn("Invalid input - enter a value between 0 and %d or 'q' to quit." % (i-1))
  463.                     continue
  464.  
  465.                 break
  466.  
  467.             print printers[x]
  468.             printer_name, device_uri = printers[x]
  469.  
  470.  
  471.     log.info(utils.bold("Using printer %s (%s)" % (printer_name, device_uri)))
  472.  
  473.     ppd_file = cups.getPPD(printer_name)
  474.  
  475.     if ppd_file is not None and os.path.exists(ppd_file):
  476.         if file(ppd_file, 'r').read(8192).find('HP Fax') == -1:
  477.             log.error("Fax configuration error. The CUPS fax queue for '%s' is incorrectly configured. Please make sure that the CUPS fax queue is configured with the 'HP Fax' Model/Driver." % printer_name)
  478.             sys.exit(1)
  479.  
  480.     hpssd_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  481.     try:
  482.         hpssd_sock.connect((prop.hpssd_host, prop.hpssd_port))
  483.     except socket.error:
  484.         log.error("Unable to contact HPLIP I/O (hpssd).")
  485.         sys.exit(1) 
  486.  
  487.     out_buffer = buildMessage("RegisterGUIEvent", None, 
  488.                               {'type': 'fax', 
  489.                                'username': username})
  490.  
  491.     hpssd_sock.send(out_buffer)
  492.  
  493.     if not args:
  494.         log.error("No files specfied to send. Please specify the file(s) to send on the command line.")
  495.         usage()
  496.  
  497.     file_list = []
  498.  
  499.     for f in args:
  500.  
  501.         #
  502.         # Submit each file to CUPS for rendering by hpijsfax
  503.         #
  504.         path = os.path.realpath(f)
  505.         log.debug(path)
  506.         mime_type = magic.mime_type(path)
  507.  
  508.         if mime_type == 'application/hplip-fax': # .g3
  509.             log.info("\nPreparing fax file %s..." % f)
  510.             fax_file_fd = file(f, 'r')
  511.             header = fax_file_fd.read(fax.FILE_HEADER_SIZE)
  512.             fax_file_fd.close()
  513.  
  514.             mg, version, pages, hort_dpi, vert_dpi, page_size, \
  515.                 resolution, encoding, reserved1, reserved2 = struct.unpack(">8sBIHHBBBII", header)
  516.  
  517.             if mg != 'hplip_g3':
  518.                 log.error("%s: Invalid file header. Bad magic." % f)
  519.                 sys.exit(1)
  520.  
  521.             file_list.append((f, mime_type, "", "", pages))
  522.  
  523.         else:
  524.             all_pages = True 
  525.             page_range = ''
  526.             page_set = 0
  527.             nup = 1
  528.  
  529.             cups.resetOptions()
  530.  
  531.             if mime_type in ["application/x-cshell",
  532.                              "application/x-perl",
  533.                              "application/x-python",
  534.                              "application/x-shell",
  535.                              "text/plain",] and prettyprint:
  536.  
  537.                 cups.addOption('prettyprint')
  538.  
  539.             if nup > 1:
  540.                 cups.addOption('number-up=%d' % nup)
  541.  
  542.             cups_printers = cups.getPrinters()
  543.             printer_state = cups.IPP_PRINTER_STATE_STOPPED
  544.             for p in cups_printers:
  545.                 if p.name == printer_name:
  546.                     printer_state = p.state
  547.  
  548.             log.debug("Printer state = %d" % printer_state)
  549.  
  550.             if printer_state == cups.IPP_PRINTER_STATE_IDLE:
  551.                 log.debug("Printer name = %s file = %s" % (printer_name, path))
  552.                 sent_job_id = cups.printFile(printer_name, path, os.path.basename(path))
  553.                 log.info("\nRendering file '%s' (job %d)..." % (path, sent_job_id))
  554.                 log.debug("Job ID=%d" % sent_job_id)
  555.             else:
  556.                 log.error("The CUPS queue for '%s' is in a stopped or busy state. Please check the queue and try again." % printer_name)
  557.                 sys.exit(1)
  558.  
  559.             cups.resetOptions()
  560.  
  561.             #
  562.             # Wait for fax to finish rendering
  563.             #
  564.  
  565.             end_time = time.time() + 120.0 
  566.             while time.time() < end_time:
  567.                 log.debug("Waiting for fax...")
  568.                 fields, data, result_code = \
  569.                     msg.xmitMessage(hpssd_sock, "FaxCheck", None,
  570.                                    {"username": prop.username})
  571.  
  572.                 if result_code == ERROR_FAX_READY:
  573.                     username = fields['username']
  574.                     job_id = fields['job-id']
  575.                     job_size = fields['job-size']
  576.                     title = fields['title']
  577.  
  578.                     if job_id == sent_job_id:
  579.                         break
  580.  
  581.                 elif result_code == ERROR_FAX_PROCESSING:
  582.                     log.debug("Fax is being rendered...")
  583.  
  584.                 time.sleep(1)
  585.  
  586.             else:
  587.                 log.error("Timeout waiting for rendering. Canceling job #%d..." % sent_job_id)
  588.                 cups.cancelJob(sent_job_id)
  589.                 sys.exit(1)
  590.  
  591.             #
  592.             # Transfer the rendered data from hpssd to a .g3 file
  593.             #
  594.             log.info("\nTransfering fax data...")
  595.  
  596.             fax_dir = os.path.expanduser("~/hpfax")
  597.  
  598.             if not os.path.exists(fax_dir):
  599.                 os.mkdir(fax_dir)
  600.  
  601.             fax_file = os.path.expanduser(os.path.join(fax_dir, "hpfax-%d.g3" % sent_job_id))
  602.             log.debug("Fax file = %s" % fax_file)
  603.  
  604.             fd = file(fax_file, 'w')
  605.             bytes_read = 0
  606.             header_read = False
  607.             total_pages = 0
  608.  
  609.             while True:
  610.                 fields, data, result_code = \
  611.                     msg.xmitMessage(hpssd_sock, "FaxGetData", None,
  612.                                      {"username": username,
  613.                                       "job-id": sent_job_id,
  614.                                      })
  615.  
  616.                 if data and result_code == ERROR_SUCCESS:
  617.                     fd.write(data)
  618.                     bytes_read += len(data)
  619.  
  620.                     if not header_read and len(data) >= fax.FILE_HEADER_SIZE:
  621.                         mg, version, total_pages, hort_dpi, vert_dpi, page_size, \
  622.                             resolution, encoding, reserved1, reserved2 = \
  623.                             struct.unpack(">8sBIHHBBBII", data[:fax.FILE_HEADER_SIZE])
  624.  
  625.                         log.debug("Magic=%s Ver=%d Pages=%d hDPI=%d vDPI=%d Size=%d Res=%d Enc=%d" %
  626.                                   (mg, version, total_pages, hort_dpi, vert_dpi, page_size, resolution, encoding))
  627.  
  628.                         header_read = True
  629.  
  630.                 else:
  631.                     break # Done
  632.  
  633.             fd.close()
  634.             log.debug("Transfered %d bytes" % bytes_read)
  635.             file_list.append((fax_file, mime_type, "", title, total_pages))
  636.  
  637.     #
  638.     # Insure that the device is in an OK state
  639.     #
  640.  
  641.     log.debug("\nChecking device state...")
  642.     try:
  643.         dev = fax.FaxDevice(device_uri=device_uri, 
  644.                             printer_name=printer_name)
  645.  
  646.         try:
  647.             dev.open()
  648.         except Error, e:
  649.             log.warn(e.msg)
  650.  
  651.         try:
  652.             dev.queryDevice(quick=True)
  653.         except Error, e:
  654.             log.error("Query device error (%s)." % e.msg)
  655.             dev.error_state = ERROR_STATE_ERROR
  656.  
  657.         if dev.error_state > ERROR_STATE_MAX_OK:
  658.             log.error("Device is busy or in an error state (code=%d). Please wait for the device to become idle or clear the error and try again." % dev.error_state)
  659.             sys.exit(1)
  660.             
  661.         user_cfg.last_used.device_uri = dev.device_uri
  662.  
  663.         log.debug("File list:")
  664.  
  665.         for f in file_list:
  666.             log.debug(str(f))
  667.  
  668.         service.sendEvent(hpssd_sock, EVENT_START_FAX_JOB, device_uri=device_uri)
  669.  
  670.         update_queue = Queue.Queue()
  671.         event_queue = Queue.Queue()
  672.  
  673.         log.info("\nSending fax...")
  674.         if not dev.sendFaxes(phone_num_list, file_list, "", 
  675.                              "", None, printer_name,
  676.                              update_queue, event_queue):
  677.  
  678.             log.error("Send fax is active. Please wait for operation to complete.")
  679.             service.sendEvent(hpssd_sock, EVENT_FAX_JOB_FAIL, device_uri=device_uri)
  680.             sys.exit(1)
  681.  
  682.         try:
  683.             cont = True
  684.             while cont:
  685.                 while update_queue.qsize():
  686.                     try:
  687.                         status, page_num, phone_num = update_queue.get(0)
  688.                     except Queue.Empty:
  689.                         break
  690.  
  691.                     if status == fax.STATUS_IDLE:
  692.                         log.debug("Idle")
  693.  
  694.                     elif status == fax.STATUS_PROCESSING_FILES:
  695.                         log.info("\nProcessing page %d" % page_num)
  696.  
  697.                     elif status == fax.STATUS_DIALING:
  698.                         log.info("\nDialing %s..." % phone_num)
  699.  
  700.                     elif status == fax.STATUS_CONNECTING:
  701.                         log.info("\nConnecting to %s..." % phone_num)
  702.  
  703.                     elif status == fax.STATUS_SENDING:
  704.                         log.info("\nSending page %d to %s..." % (page_num, phone_num))
  705.  
  706.                     elif status == fax.STATUS_CLEANUP:
  707.                         log.info("\nCleaning up...")
  708.  
  709.                     elif status in (fax.STATUS_ERROR, fax.STATUS_BUSY, fax.STATUS_COMPLETED):
  710.                         cont = False
  711.  
  712.                         if status  == fax.STATUS_ERROR:
  713.                             log.error("Fax send error.")
  714.                             service.sendEvent(hpssd_sock, EVENT_FAX_JOB_FAIL, device_uri=device_uri)
  715.  
  716.                         elif status == fax.STATUS_BUSY:
  717.                             log.error("Fax device is busy. Please try again later.")
  718.                             service.sendEvent(hpssd_sock, EVENT_FAX_JOB_FAIL, device_uri=device_uri)
  719.  
  720.                         elif status == fax.STATUS_COMPLETED:
  721.                             log.info("\nCompleted successfully.")
  722.                             service.sendEvent(hpssd_sock, EVENT_END_FAX_JOB, device_uri=device_uri)
  723.  
  724.                 update_spinner()
  725.                 time.sleep(2)
  726.  
  727.             cleanup_spinner()
  728.  
  729.         except KeyboardInterrupt:
  730.             event_queue.put((fax.EVENT_FAX_SEND_CANCELED, '', '', ''))
  731.             service.sendEvent(hpssd_sock, EVENT_FAX_JOB_CANCELED, device_uri=device_uri)
  732.             log.error("Cancelling...")
  733.  
  734.         dev.waitForSendFaxThread()
  735.  
  736.     finally:
  737.         dev.close()
  738.         service.sendEvent(hpssd_sock, EVENT_END_FAX_JOB, device_uri=device_uri)
  739.         hpssd_sock.close()
  740.  
  741.     log.info("\nDone.")
  742.  
  743.  
  744. sys.exit(0)
  745.  
  746.